home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / appletalk / uab.shar / kip_mpx.c < prev    next >
C/C++ Source or Header  |  1990-07-12  |  10KB  |  437 lines

  1. static char rcsid[] = "$Author: cck $ $Date: 88/09/14 10:19:45 $";
  2. static char rcsident[] = "$Header: /src/local/mac/cap/etalk/RCS/kip_mpx.c,v 1.19 88/09/14 10:19:45 cck Rel $";
  3. static char revision[] = "$Revision: 1.19 $";
  4.  
  5. /*
  6.  * kip_mpx.c - talks to cap processes via udp
  7.  *
  8.  *  demultiplexing communications point with various processes.
  9.  *  Two versions in here: one version speaks directly to KIP module
  10.  *  CAP clients (KIP).  The other speaks on a modified range (MKIP)
  11.  *  
  12.  *  KIP writes atalk.local and cannot be used when the rebroadcaster
  13.  *    is in use.  NOTE: THIS DOES NOT WORK CORRECTLY.
  14.  *  MKIP writes matalk.local (debugging mostly)
  15.  *
  16.  *  This version really cheats and uses a different range of ports,
  17.  *  but the same encapsulation used for kip.
  18.  *
  19.  *
  20.  * Copyright (c) 1988 by The Trustees of Columbia University 
  21.  *  in the City of New York.
  22.  *
  23.  * Permission is granted to any individual or institution to use,
  24.  * copy, or redistribute this software so long as it is not sold for
  25.  * profit, provided that this notice and the original copyright
  26.  * notices are retained.  Columbia University nor the author make no
  27.  * representations about the suitability of this software for any
  28.  * purpose.  It is provided "as is" without express or implied
  29.  * warranty.
  30.  *
  31.  * Edit History:
  32.  *
  33.  *  April 3, 1988  CCKim Created
  34.  *
  35. */
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <sys/types.h>
  39. #include <sys/socket.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/uio.h>
  42. #include <sys/time.h>
  43. #include <net/if.h>
  44. #include <netinet/in.h>
  45.  
  46. #include <netat/appletalk.h>
  47. #include "mpxddp.h"
  48. #include "gw.h"
  49. #include "log.h"
  50.  
  51. #define LOG_STD 2
  52.  
  53. /*
  54.   ethertalk to kip - try 1:
  55.   o forward packets by sending to ddp udp port
  56.   o receive packets by having the remote send to "bridge" socket
  57.   o much like kip methods except different socket range and fewer
  58.     conditions in lower level code
  59. */
  60.  
  61. #ifndef MTAB
  62. # define MTAB "/etc/matalk.local"
  63. #endif
  64. #ifndef TAB
  65. # define TAB "/etc/atalk.local"
  66. #endif
  67.  
  68. /* handle kip fakeout */
  69. #define mkip_rebPort 903
  70. #define kip_rebPort 902
  71.  
  72. #define mddp2ipskt(s)  (((s)&0x80) ? (s)+ddpNWKSUnix :(s)+200)
  73.  
  74. struct kipdef {
  75.  int s;                /* socket */
  76.  word net;
  77.  byte node;
  78.  byte bridge_node;
  79.  struct sockaddr_in sin;
  80. };
  81.  
  82. #define MKIP_HANDLE 0
  83. #define KIP_HANDLE 1
  84. #define NUM_KIP_HANDLE 2
  85.  
  86. #define VALID_HANDLE(h) ((h) >= 0 && (h) < NUM_KIP_HANDLE)
  87. #define INVALID_HANDLE(h) ((h) >= NUM_KIP_HANDLE || (h) < 0)
  88. private struct kipdef kipdefs[NUM_KIP_HANDLE];
  89.  
  90. #define KIP_PRIMARY 0        /* primary listening */
  91. #define KIP_SECONDARY 1        /* secondary: local to process */
  92.  
  93. /* destination */
  94. private struct in_addr desthost;
  95.  
  96. private DDP kddp;
  97. private LAP klap;
  98. private char kbuf[ddpMaxData+ddpSize]; /* add in space for lap */
  99.  
  100. private int kip_init();
  101. private int mkip_init();
  102. private int kip_grab();
  103. private int kips_ahoy();
  104. private int kip_sendddp();
  105. private int kip_havenode();
  106. private int kip_havenet();
  107. private int kip_havezone();
  108.  
  109. export struct mpxddp_module mkip_mpx = {
  110.   "modified KIP forwarding",
  111.   "MKIP",
  112.   mkip_init,
  113.   NULL,                /* grab, don't do for now (ddpsrvc not done) */
  114.   kip_sendddp,
  115.   kip_havenode,
  116.   kip_havenet,
  117.   kip_havezone
  118. };
  119.  
  120. export struct mpxddp_module kip_mpx = {
  121.   "KIP forwarding",
  122.   "KIP",
  123. #ifdef notdef
  124.   /* doesn't work right because of the way kip routing is done, sigh */
  125.   kip_init,
  126.   NULL,                /* grab, don't do for now (ddpsrvc not done) */
  127.   kip_sendddp,
  128.   kip_havenode,
  129.   kip_havenet,
  130.   kip_havezone
  131. #else
  132.   NULL,                /* init */
  133.   NULL,                /* grab, don't do for now (ddpsrvc not done) */
  134.   NULL,                /* senddp */
  135.   NULL,                /* havenode */
  136.   NULL,                /* have net */
  137.   NULL                /* have zone */
  138. #endif
  139. };
  140.  
  141. private
  142. kip_listener(fd, k, level)
  143. int fd;
  144. struct kipdef *k;
  145. int level;
  146. {
  147.   struct msghdr msg;
  148.   struct iovec iov[3];
  149.   int len;
  150.   struct sockaddr_in from_sin;
  151.   
  152.   /* should check k */
  153.   iov[0].iov_base = (caddr_t)&klap;
  154.   iov[0].iov_len = lapSize;
  155.   iov[1].iov_base = (caddr_t)&kddp;
  156.   iov[1].iov_len = ddpSize;
  157.   iov[2].iov_base = kbuf;
  158.   iov[2].iov_len = ddpMaxData;
  159.   msg.msg_name = (caddr_t) &from_sin;
  160.   msg.msg_namelen = sizeof(from_sin);
  161.   msg.msg_iov = iov;
  162.   msg.msg_iovlen = 3;
  163.   msg.msg_accrights = 0;
  164.   msg.msg_accrightslen = 0;
  165.   if ((len = recvmsg(fd,&msg,0)) < 0) {
  166.     log(LOG_LOG|L_UERR, "recvmsg: kip listener");
  167.     return(len);
  168.   }
  169.   /* could do rebroadcaster work here */
  170.   if (len < (lapSize+ddpSize))
  171.     return(-1);
  172.   len -= (lapSize + ddpSize);
  173.   if (klap.type != lapDDP)
  174.     return(-1);
  175.   switch (level) {
  176.   case KIP_PRIMARY:
  177.     if (klap.src != k->node)    /* drop!  must have wrong configuration */
  178.       return(-1);
  179.     if (kddp.srcNode != k->node || (kddp.srcNet != k->net && kddp.srcNet != 0))
  180.       return(-1);
  181.     break;
  182.   case KIP_SECONDARY:
  183.     /* always accept? */
  184.     break;
  185.   }
  186.   ddp_output(NULL, &kddp, (byte *)kbuf, len);
  187.   return(0);
  188. }
  189.  
  190. /*
  191.  * initialize kip forwarding
  192.  *
  193. */
  194. private int
  195. mkip_init()
  196. {
  197.   static int inited = FALSE;
  198.   int i;
  199.  
  200.   if (inited)
  201.     return(-1);
  202.   if ((i = kips_ahoy(MKIP_HANDLE)) >= 0)
  203.     inited = TRUE;
  204.   return(i);
  205. }
  206.  
  207. private int
  208. kip_init()
  209. {
  210.   static int inited = FALSE;
  211.   int i;
  212.  
  213.   if (inited)
  214.     return(-1);
  215.   if ((i = kips_ahoy(KIP_HANDLE)) >= 0)
  216.     inited = TRUE;
  217.   return(i);
  218. }
  219.  
  220. private int
  221. kips_ahoy(h)
  222. {
  223.   int cc;
  224.   struct kipdef *k;
  225.  
  226.   if (h != MKIP_HANDLE && h != KIP_HANDLE)
  227.     return(-1);
  228.   k = &kipdefs[h];
  229.   k->net = 0;
  230.   k->node = 0;
  231.   k->bridge_node = 0;
  232.   desthost.s_addr = inet_addr("127.0.0.1");
  233.   if (desthost.s_addr == -1)
  234.     return(-1);
  235.   /* no need to bind since we don't recv on this socket, just send... */
  236.   if ((k->s = socket(AF_INET,SOCK_DGRAM,0)) < 0) {
  237.     log(LOG_LOG|L_UERR, "socket: kip init");
  238.     return(-1);
  239.   }
  240.   k->sin.sin_family = AF_INET;
  241.   switch (h) {
  242.   case MKIP_HANDLE:
  243.     k->sin.sin_addr.s_addr = desthost.s_addr;
  244.     k->sin.sin_port = htons(mkip_rebPort);
  245.     break;
  246.   case KIP_HANDLE:
  247.     k->sin.sin_addr.s_addr = INADDR_ANY;
  248.     k->sin.sin_port = htons(kip_rebPort);
  249.     break;
  250.   }
  251.   if ((cc = bind(k->s, (caddr_t)&k->sin, sizeof(k->sin))) < 0) {
  252.     close(k->s);
  253.     log(LOG_LOG|L_UERR, "bind: kip init");
  254.     return(cc);
  255.   }
  256.   fdlistener(k->s, kip_listener, k, KIP_PRIMARY);
  257.   return(h);
  258. }
  259.  
  260. private int
  261. kip_grab(hdl, skt)
  262. int hdl;
  263. int skt;
  264. {
  265.   int fd, e;
  266.   struct sockaddr_in lsin;
  267.  
  268.   if (INVALID_HANDLE(hdl))
  269.     return(-1);
  270.   
  271.   if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  272.     log(LOG_STD|L_UERR, "kip grab: socket for skt %d", skt);
  273.     return(fd);
  274.   }
  275.   lsin.sin_family = AF_INET;
  276.   /* bind only for localhost if mkip */
  277.   switch (hdl) {
  278.   case MKIP_HANDLE:
  279.     lsin.sin_addr.s_addr = desthost.s_addr;
  280.     lsin.sin_port = htons(ddp2ipskt(skt));
  281.     break;
  282.   case KIP_HANDLE:
  283.     lsin.sin_addr.s_addr = INADDR_ANY;
  284.     lsin.sin_port = (word)htons(mddp2ipskt(skt));
  285.     break;
  286.   }
  287.   if (lsin.sin_port == 0) {    /* same swapped or unswapped */
  288.     close(fd);            /* bad ddp socket */
  289.     return(-1);
  290.   }
  291.   if ((e = bind(fd, (caddr_t)&lsin, sizeof(lsin))) < 0) {
  292.     log(LOG_STD|L_UERR, "kip grab: bind for skt %d", skt);
  293.     return(fd);
  294.   }
  295.   fdlistener(kipdefs[hdl].s, kip_listener, KIP_SECONDARY);
  296.   return(fd);
  297. }
  298.  
  299. /*
  300.  * send along a ddp packet to the appropriate process
  301.  *
  302. */
  303. private int
  304. kip_sendddp(hdl, ddp, data, cc)
  305. int hdl;
  306. DDP *ddp;
  307. caddr_t data;
  308. int cc;
  309. {
  310.   struct msghdr msg;
  311.   word destskt;
  312.   int err;
  313.   struct iovec iov[4];
  314.   LAP lap;
  315.   int t;
  316.   struct kipdef *k;
  317.  
  318.   if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
  319.     return(-1);
  320.   k = &kipdefs[hdl];
  321.  
  322.   /* I THINK this is the right place for this -- this way, the demuxer */
  323.   /* could possible handle multiple networks */
  324.   if (ddp->dstNet != k->net && ddp->dstNode != k->node) /* drop */
  325.     return(0);
  326.  
  327.   if (hdl == KIP_HANDLE)
  328.     destskt = (word)htons(ddp2ipskt(ddp->dstSkt)+128);
  329.   else
  330.     destskt = (word)htons(mddp2ipskt(ddp->dstSkt));
  331.   /* establish a dummy lap header */
  332.   lap.type = lapDDP;
  333.   lap.dst = k->node;
  334.   lap.src = ddp->srcNode;
  335.   iov[IOV_LAP_LVL].iov_base = (caddr_t) ⪅ /* LAP header */
  336.   iov[IOV_LAP_LVL].iov_len = lapSize;       /* size  */
  337.   iov[IOV_DDP_LVL].iov_base = (caddr_t) ddp;
  338.   iov[IOV_DDP_LVL].iov_len = ddpSize;
  339.   /* figure out what the data length should be */
  340.   t = (ntohs(ddp->length)&ddpLengthMask) - ddpSize;
  341.   /* if data size passed down is too large, then truncate.  (sunos */
  342.   /* trailing bytes or packet less than 60 bytes */
  343.   /* so, pass back min of cc, length */
  344.   iov[2].iov_len = (cc > t) ? t : cc;
  345.   iov[2].iov_base = data;
  346.   /* send through */
  347.   k->sin.sin_addr = desthost;
  348.   k->sin.sin_port = destskt;
  349.   msg.msg_name = (caddr_t) &k->sin;
  350.   msg.msg_namelen = sizeof(k->sin);
  351.   msg.msg_iov = iov;
  352.   msg.msg_iovlen = 3;
  353.   msg.msg_accrights = 0;
  354.   msg.msg_accrightslen = 0;
  355.   if ((err = sendmsg(k->s,&msg,0)) < 0)
  356.     log(LOG_LOG|L_UERR, "sendmsg: kip write");
  357.   return(err);  
  358. }
  359.  
  360. /*
  361.  * have node now  -- just remember
  362.  *
  363. */
  364. private int
  365. kip_havenode(hdl, node)
  366. int hdl;
  367. byte node;
  368. {
  369.   if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
  370.     return(FALSE);
  371.   kipdefs[hdl].node = node;
  372.   return(TRUE);
  373. }
  374.  
  375. /*
  376.  * have network now
  377.  *
  378. */
  379. private int
  380. kip_havenet(hdl, net, node)
  381. word net;
  382. byte node;
  383. {
  384.   if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
  385.     return(FALSE);
  386.   kipdefs[hdl].net = net;
  387.   kipdefs[hdl].bridge_node = node;
  388.   return(TRUE);
  389. }
  390.  
  391. /*
  392.  * have zone: ready to go
  393.  *
  394. */
  395. private int
  396. kip_havezone(hdl, zone)
  397. int hdl;
  398. byte *zone;
  399. {
  400.   FILE *fp;
  401.   int i;
  402.   struct kipdef *k;
  403.   char *file;
  404.  
  405.   if (hdl != MKIP_HANDLE && hdl != KIP_HANDLE)
  406.     return(FALSE);
  407.   k = &kipdefs[hdl];
  408.   file = (hdl == MKIP_HANDLE) ? MTAB : TAB;
  409.   if ((fp = fopen(file,"w")) == NULL) {
  410.     log(LOG_LOG|L_UERR, "can't open %s", file);
  411.     return(FALSE);
  412.   }
  413.   fprintf(fp, "%d.%d %d ",
  414.       nkipnetnumber(k->net), nkipsubnetnumber(k->net),
  415.       k->node);
  416.   /* translate it for atalkdbm - ugh */
  417.   for (i = *zone++; i ; i--, zone++) {
  418.     switch (*zone) {
  419.     case ' ':
  420.       putc(' ', fp);
  421.       break;
  422.     case '_':
  423.       putc('_', fp);
  424.       putc('_', fp);
  425.       break;
  426.     default:
  427.       putc(*zone, fp);
  428.     }
  429.   }
  430.   putc('\n', fp);
  431.   fprintf(fp, "%d.%d %d 127.0.0.1\n",
  432.       nkipnetnumber(k->net), nkipsubnetnumber(k->net),
  433.       k->bridge_node);
  434.   fclose(fp);
  435.   return(TRUE);
  436. }
  437.